﻿using System;
using System.Collections.Generic;

using RexToy;
using RexToy.ORM;
using RexToy.ORM.Configuration;
using RexToy.UI.WinForm;
using RexToy.UI.WinForm.Pmlx;
using RexToy.UI.WinForm.ViewModel;

using Studio.Common;
using Studio.Model;

namespace Studio.ViewModel
{
    public class FrmConnectVM : ViewModelBase
    {
        public FrmConnectVM()
        {
            _dbModel = DatabaseModel.CreateModel(_database);
        }

        private Database _database;
        public Database Database
        {
            get { return _database; }
            set
            {
                _database = value;
                _dbModel = DatabaseModel.CreateModel(_database);
                this.OnPropertyChange<FrmConnectVM>(vm => vm.Server);
            }
        }

        private IDatabaseModel _dbModel;

        public string Server
        {
            get { return _dbModel.Server; }
            set { _dbModel.Server = value; }
        }

        public string Schema
        {
            get { return _dbModel.Schema; }
            set { _dbModel.Schema = value; }
        }

        public string UserName
        {
            get { return _dbModel.UserName; }
            set { _dbModel.UserName = value; }
        }

        public string Password
        {
            get { return _dbModel.Password; }
            set { _dbModel.Password = value; }
        }

        public bool IntegratedSecurity
        {
            get { return _dbModel.IntegratedSecurity; }
            set
            {
                _dbModel.IntegratedSecurity = value;
                this.OnPropertyChange<FrmConnectVM>(m => m.IntegratedSecurity);
            }
        }

        public bool IntegratedSecurityCheckable
        {
            get { return this._database == Database.SQLServer; }
        }

        private FrmMainVM _mainVM;
        public void SetMainVM(FrmMainVM vm)
        {
            _mainVM = vm;
        }

        private DBConfig _cfg;
        private void BuildConnectInfo()
        {
            _cfg = new DBConfig(_dbModel.ConnectString, _dbModel.Provider, _dbModel.Dialect, _dbModel.DialectProvider);
        }

        public void Test()
        {
            BuildConnectInfo();
            ORMConfig.Initialize(_cfg);
            ISession s = null;
            try
            {
                s = SessionFactory.OpenSession();
                _mainVM.TestConnect("Test Pass.");
            }
            catch (SessionException ex)
            {
                _mainVM.TestConnect("Test Fail: " + ex.InnerException.Message);
            }
            finally
            {
                if (s != null)
                    s.Dispose();
            }
        }

        public void Connect()
        {
            BuildConnectInfo();
            ORMConfig.Initialize(_cfg);
            ISession s = null;
            try
            {
                s = SessionFactory.OpenSession();
                //Note:Strange issue: if call as extension, _database.GetDescription will have error, said need reference System.Window.Forms, that's not acceptable.
                _mainVM.Connect(true, EnumEx.GetDescription(_database), string.Empty, _dbModel);
                this.OnClose();
            }
            catch (SessionException ex)
            {
                _mainVM.Connect(false, EnumEx.GetDescription(_database), "Connect error.", _dbModel);
                this.OnClose();
            }
            finally
            {
                if (s != null)
                    s.Dispose();
            }
        }

        private IUICommand _testCmd;
        public IUICommand TestCommand
        {
            get
            {
                if (_testCmd == null)
                {
                    _testCmd = new ActionCommand(() => this.Test());
                }
                return _testCmd;
            }
        }

        private IUICommand _okCmd;
        public IUICommand OKCommand
        {
            get
            {
                if (_okCmd == null)
                {
                    _okCmd = new ActionCommand(() => this.Connect());
                }
                return _okCmd;
            }
        }
    }
}
